fix(rust): deterministic clustered vcov — first-appearance cluster aggregation#653
Conversation
Overall Assessment✅ Looks good — no unmitigated P0/P1 findings. Executive Summary
MethodologyNo blocking findings. Severity: N/A Code QualityNo findings. Severity: N/A PerformanceNo findings. Severity: N/A MaintainabilityNo findings. Severity: N/A Tech DebtNo findings. Severity: N/A SecurityNo findings. Severity: N/A Documentation/TestsSeverity: P3 Tests not run in this read-only review sandbox. |
91eff7c to
2f76a32
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment✅ Looks good — no unmitigated P0/P1 findings. Executive Summary
MethodologyNo blocking findings. Severity: N/A Code QualityNo findings. Severity: N/A PerformanceNo findings. Severity: N/A MaintainabilityNo findings. Severity: N/A Tech DebtNo findings. Severity: N/A SecurityNo findings. Severity: N/A Documentation/TestsSeverity: P3 |
…gregation The cluster-score aggregation in compute_robust_vcov (also reached via solve_ols(return_vcov=True)) built its (G,k) cluster-scores matrix in HashMap iteration order, which is SipHash-randomized per call: mathematically identical, but the GEMM accumulation order changed on every invocation, wobbling the clustered vcov at ~1e-14 (3 distinct values across 8 identical calls; the Python backend is bit-stable). Rows now accumulate in first-appearance order — ascending for the factorized 0..G-1 ids the Python dispatcher passes, matching NumPy's groupby order. Verified 1 distinct value across 50 identical calls; NumPy parity unchanged (~1e-14 cross-backend GEMM tolerance). Bit-identity regression tests cover contiguous and non-contiguous unsorted cluster ids. Resolves the TODO row currently in flight on PR #647 (row deletion follows once both merge). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2f76a32 to
fcbbf4e
Compare
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
fcbbf4e to
5aa51c7
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment✅ Looks good — no unmitigated P0/P1 findings. Executive Summary
MethodologyFinding: None. Code QualityFinding: None. PerformanceFinding: None. MaintainabilityFinding: None. Tech DebtFinding: None. SecurityFinding: None. Documentation/TestsFinding: None. |
…w P2) The TODO-row deletion left no file-visible resolution trail; the REGISTRY now documents the root cause (SipHash HashMap iteration order), the fix (first-appearance aggregation, #653), and the regression tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Rust clustered-vcov run-to-run nondeterminism: root-caused and fixed by #653 (SipHash HashMap iteration order -> first-appearance remap; 50 identical calls now bit-identical). The row deferred its own deletion until the fix merged; #653 merged 2026-07-08. - HonestDiD Delta^SD optimal-FLCI center parity: the row was already marked LANDED (SE-audit B2b, #635) with Effort 'Done' - it documented completed work, not remaining work. No code changes; CHANGELOG untouched per convention for TODO-hygiene commits (the underlying fixes carried their own entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…w P2) The TODO-row deletion left no file-visible resolution trail; the REGISTRY now documents the root cause (SipHash HashMap iteration order), the fix (first-appearance aggregation, #653), and the regression tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…653; HonestDiD B2b) (#662) * docs(todo): drop two resolved Actionable rows - Rust clustered-vcov run-to-run nondeterminism: root-caused and fixed by #653 (SipHash HashMap iteration order -> first-appearance remap; 50 identical calls now bit-identical). The row deferred its own deletion until the fix merged; #653 merged 2026-07-08. - HonestDiD Delta^SD optimal-FLCI center parity: the row was already marked LANDED (SE-audit B2b, #635) with Effort 'Done' - it documented completed work, not remaining work. No code changes; CHANGELOG untouched per convention for TODO-hygiene commits (the underlying fixes carried their own entries). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs(registry): record the #653 clustered-vcov determinism fix (review P2) The TODO-row deletion left no file-visible resolution trail; the REGISTRY now documents the root cause (SipHash HashMap iteration order), the fix (first-appearance aggregation, #653), and the regression tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * docs: fix stale TODO-row reference + align the determinism-count claim (review P3s) The wild-bootstrap chunking comment pointed at the TODO row this PR deletes; it now cites the REGISTRY determinism note + the TestClusterVcovDeterminism regression. The REGISTRY '50 identical calls' claim now distinguishes the in-fix 50-call probe from the shipped 20-repeat regression loops. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
compute_robust_vcov(also reached viasolve_ols(return_vcov=True)) built its (G, k) cluster-scores matrix inHashMapiteration order — SipHash-randomized per call. Mathematically identical, but the GEMM accumulation order changed on every invocation, wobbling the clustered vcov at ~1e-14 (3 distinct values across 8 identical calls; the Python backend is bit-stable; thread pinning had no effect, which pointed away from BLAS and at the map).to_owned+ map-entry churn is gone (direct accumulation into the matrix).Methodology references (required if estimator / math changes)
Validation
tests/test_rust_backend.py::TestClusterVcovDeterminism(2 bit-identity tests, 20 repeat-calls each).tests/test_rust_backend.py+tests/test_linalg.pypass (253); cargo fmt/check clean.Security / privacy
Generated with Claude Code